#ifndef DFRT_HDR
#define DFRT_HDR
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

// Structure, allocated for each code block
// that describes its static properties. 
// Position, initial sc ...

// Struct wrvec...
#include <delayed_write.h>


#define DFRT_INFO_CONTENT \
    void (*fn)();\
    long flags;\
    struct misc_info * misc;\
    long types[]

struct dfrt_info {
    DFRT_INFO_CONTENT;
} __attribute__((__packed__));

struct frame_struct {
  struct dfrt_info *infos;
  int sc;
  struct frame_struct *ret[];
} __attribute__((__packed__))
;


struct misc_info {
  char * fname;
  char * description;
} __attribute__((__packed__))
;




/* Get the frame pointer of the current thread */
extern struct frame_struct * dfrt_get_cfp();

/* Create a new thread, with frame pointer size, and sync counter */
extern struct frame_struct  * dfrt_tcreate( int sc, int fp_size);


/* Decrease the synchronization counter by one */
extern void dfrt_effective_tdecrease( struct frame_struct *fp );
extern void dfrt_delayed_tdecrease(struct frame_struct *frame );

// Used to synchronize a decrease with a separate acquire.
// For example, if the tdecrease is called to
static inline void dfrt_delayeduntil_tdecrease( struct frame_struct *to_decrease, void * to_wait ) {
    // TODO : implement it !
    // Be careful : not all tdec are done at tend, if provided in the wrdesc of an owm acquire,
     // they'll proceed otherwise.
    dfrt_delayed_tdecrease(to_decrease);
}

/* Destroy (free) the current thread */
extern void dfrt_tend();

/* Experimental change of the API */
//extern struct frame_struct *DFRT_tupdate( struct frame_struct *fp,
//                          int sc_dec,
//                          struct wish_list *wlist);


/* Blocking, explicit frame acquire */
extern void dfrt_tacquire( void *fp);
/* Explicit release. */
extern void dfrt_trelease( void *fp);


extern void dfrt_init( int nodenum, int threadnum, void* real_main );

void dfrt_teardown();


extern int dfrt_whoami();

extern int dfrt_get_thread_num();

extern int dfrt_get_node_num();

extern int dfrt_get_num_nodes();

#ifdef __cplusplus
}
#endif

#endif
